package com.tanhua.gateway.filters;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: tanhua
 * @description:
 * @author: MR.peng
 * @create: 2022-03-30 15:43
 **/

/*
 * 网关过滤器
 *   1、实现两个接口
 *   2、实现两个方法
 *   3、过滤器交给容器管理
 *   4、在filter方法中完成过滤器的核心处理逻辑
 *
 * */

@Component
public class AuthFilter implements GlobalFilter, Ordered {


    //读取配置文件，会自动获取配置字符串，如果字符串中有","隔开，自动构建一个list集合
    @Value("${gateway.excludedUrls}")
    private List<String> excludeUrls; //定义了所有不需要token检验的URL集合  /login,  /loginer

    /*
    * 过滤器的业务逻辑
    *       exchange:请求上下文--获取response,request
    *       chain：过滤器链 ---请求放行
    * */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        //1、获取请求链接
        String path = request.getURI().getPath();  //login

        //2、判断此连接是否需要通过token验证
        if(excludeUrls.contains(path)){
            //2.1、如果不需要验证，路由到服务
            return chain.filter(exchange);
        }
        //3、获取到token  (手机端token = token,前端页面token = Bearer token )
        String  token = request.getHeaders().getFirst("Authorization");
        if(!StringUtils.isEmpty(token)){
            token = token.replaceAll("Bearer","");  //针对页面端的token问题
        }
        //4、调用工具类验证token
        boolean verifyToken = JwtUtils.verifyToken(token);
        //4.1、验证通过，路由到服务
        if(verifyToken){
            return chain.filter(exchange);
        }else {
            //4.2、验证不通过，响应401
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //return response.setComplete(); //响应结束
            //携带响应数据（工作问题）
            Map<String,Object> map = new HashMap<>();
            map.put("errCode", 401);
            map.put("errMessage", "用户未登录");
            //databuffer
            //指定相应的数据头
            response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            //需要将返回的对象数据转化为byte数组
            byte[] data = JSON.toJSONBytes(map);
            //构造DataBuffer对象
            DataBuffer buffer = response.bufferFactory().wrap(data); //数据DatBuffer
            return response.writeWith(Mono.just(buffer));
        }
    }

    //指定在多个过滤（过滤器链）中的执行顺序
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE; //返回值越小，优先级越高
    }
}
